﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Nest;
using ES.Client.Filter;
using Elasticsearch.Net;

namespace ES.Client
{
    [System.Serializable]
    public class QueryParameter<T> where T : class
    {
        #region 废弃
        ///// <summary>
        ///// 获取当前泛型的DocMapping
        ///// </summary>
        ///// <returns></returns>
        //private DocMappingAttribute GetDocMapping()
        //{
        //    Type type = typeof(T);
        //    DocMappingAttribute typeAttr = null;
        //    var attributes = type.GetCustomAttributes(true).ToList();
        //    foreach (var attr in attributes)
        //    {
        //        if (attr.GetType().FullName == typeof(DocMappingAttribute).FullName)
        //        {
        //            typeAttr = attr as DocMappingAttribute;
        //            break;
        //        }
        //    }

        //    if (typeAttr == null)
        //    {
        //        var error = string.Format("{0}缺少DocMapping特性", type.FullName);
        //        throw new Exception(error);
        //    }

        //    return typeAttr;
        //}

        //public QueryParameter()
        //{
        //    var docMapping = this.GetDocMapping();

        //    this.From = 0;
        //    this.Size = 20;
        //    this.Index = docMapping.Index;
        //    this.DocType = docMapping.DocType;
        //    this.TrackScores = false;
        //    this.RequestCache = true;
        //    this.SearchType = SearchType.QueryThenFetch;
        //    this.Highlighter = new HighlightDescriptor<T>();
        //    this.Highlighter.RequireFieldMatch(false);
        //    this.Must = new QueryFilter<T>(this.Index, this.DocType);
        //    this.MustNot = new QueryFilter<T>(this.Index, this.DocType);
        //    this.Should = new QueryFilter<T>(this.Index, this.DocType);
        //    this.Sorter = new SortDescriptor<T>();
        //}
        #endregion

        internal QueryParameter(string index, string docType)
        {
            this.From = 0;
            this.Size = 20;
            this.Index = index;
            this.DocType = docType;
            this.TrackScores = false;
            this.RequestCache = true;
            this.SearchType = SearchType.QueryThenFetch;
            this.Highlighter = new HighlightDescriptor<T>();
            this.Highlighter.RequireFieldMatch(false);
            this.Source = new SourceFilterDescriptor<T>();
            this.Must = new QueryFilter<T>(this.Index, this.DocType);
            this.MustNot = new QueryFilter<T>(this.Index, this.DocType);
            this.Should = new QueryFilter<T>(this.Index, this.DocType);
            this.Sorter = new SortParameter<T>();
        }

        public string Index
        {
            get;
            internal set;
        }

        public string DocType
        {
            get;
            internal set;
        }

        /// <summary>
        /// 初始化自定义条件构造器
        /// </summary>
        /// <returns></returns>
        public QueryFilter<T> GetBuilder()
        {
            return new QueryFilter<T>(this.Index, this.DocType);
        }

        public QueryFilter<T> Must { get; set; }

        public QueryFilter<T> MustNot { get; set; }

        public QueryFilter<T> Should { get; set; }

        public SortParameter<T> Sorter { get; set; }

        public SourceFilterDescriptor<T> Source { get; set; }

        public int From { get; set; }

        public int Size { get; set; }

        public bool TrackScores { get; set; }

        public bool RequestCache { get; set; }

        public string Preference { get; set; }

        public SearchType SearchType { get; set; }

        public HighlightDescriptor<T> Highlighter { get; set; }

        internal SortDescriptor<T> BuildSorter()
        {
            var sorter = new SortDescriptor<T>();
            if (this.Sorter != null && this.Sorter.Items.Any())
            {
                var items = this.Sorter.Items;
                foreach (var item in items)
                {
                    if (item.Direction == SortDirection.ASC)
                    {
                        sorter = sorter.Field(t => t.Field(new Nest.Field() { Name = item.Field }).Ascending().IgnoreUnmappedFields().MissingLast());
                    }
                    else
                    {
                        sorter = sorter.Field(t => t.Field(new Nest.Field() { Name = item.Field }).Descending().IgnoreUnmappedFields().MissingLast());
                    }
                }
            }
            return sorter;
        }
    }
}
